﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using Site.ServiceReferenceBomberman;
using System.ServiceModel;

namespace Site.WebService
{
    [CallbackBehavior(ConcurrencyMode = ConcurrencyMode.Reentrant)]
    public class ProxyService : IDisposable, IServiceGameWebSiteCallback
    {
        public class Buffer<T> {
            bool ready;
            private T data;
            public T Data
            {
                get { return this.data; }
                set { this.data = value; this.ready = true; }
            }
            public Buffer(){
                ready = false;
            }

            public bool tryRead(out T o) {
                if(!ready) {
                    o = default(T);
                    return false;
                }
                o = data;
                return true;
            }
        }
        ServiceGameWebSiteClient client;
        Dictionary<uint,Buffer<FlashVars>> queued_players;
        public bool isConnected { get; private set; }

        private static ProxyService instance;

        public ProxyService()
        {
            InstanceContext context = new InstanceContext(this);
            try
            {
                client = new ServiceGameWebSiteClient(context, "service");
                client.register();
                client.InnerChannel.OperationTimeout = TimeSpan.FromMinutes(5);
            }
            catch (TimeoutException e)
            {
                isConnected = false;
                return;
            }
            isConnected = true;
            queued_players = new Dictionary<uint,Buffer<FlashVars>>();
        }

        void IDisposable.Dispose()
        {
            client.Close();
        }

        public static ProxyService getInstance()
        {
            return instance;
        }

        public static void create()
        {
            instance = new ProxyService();
        }

        //Callback functions

        // returns true if we can read the vars
        public bool getFlashVars(uint uid, out FlashVars vars)
        {
            return (queued_players[uid].tryRead(out vars));
        }

        void IServiceGameWebSiteCallback.notifyNewGame(Uri Adress, int Port, GameCreatedArgs_Player[] tokens)
        {
            // for each player
            foreach (GameCreatedArgs_Player arg in tokens)
            {
                // create the vars
                FlashVars vars = new FlashVars();
                vars.Adress = Adress;
                vars.Port = Port;
                vars.Token = arg.token;
                queued_players[arg.uid].Data = vars;
            }
        }

        void IServiceGameWebSiteCallback.onGameFinished(GameFinishedArgs args)
        {
            throw new NotImplementedException();
        }

        //Public functions
        public void addPlayerInRankedQueue(uint uid, Site.ServiceReferenceBomberman.MatchType type)
        {
            // create the polling object
            if(client.addPlayerInRankedQueue((uint) uid, type))
                queued_players.Add(uid,new Buffer<FlashVars>());
        }

        public int createPlayer(string player_client_id, string application_id, string player_name)
        {
            return client.createPlayer(player_client_id, application_id, player_name);
        }

        public bool isQueued(uint uid)
        {
            return queued_players.ContainsKey(uid);
        }
    }
}